package com.wip.reportingclient.services.impls;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wip.reportingclient.services.domains.ReportData;
import com.wip.reportingclient.services.domains.ReportTypeEnum;
import com.wip.reportingclient.services.interfaces.IXlsService;
import com.wip.reportingclient.services.interfaces.IWriterService;
import com.wip.reportingclient.services.interfaces.IZippingService;
import com.wip.reportingclient.services.util.CalculatorUtil;
import com.wip.reportingclient.ui.components.FormData;

@Service
public class XlsServiceImpl implements IXlsService {

	@Autowired
	private CalculatorUtil calcs;

	@Autowired
	private IZippingService zipService;

	@Autowired
	private IWriterService writeService;

	@Override
	public void createReport(HttpServletResponse response, FormData formData,
			ReportData reportData) {
		HashMap<String, HashMap<String, HashMap<String, ArrayList<Integer>>>> clientsMap = reportData
				.getDataMap();

		Map<String, ByteArrayOutputStream> bosMap = new HashMap<String, ByteArrayOutputStream>();

		// List<HSSFWorkbook> workbooks = new ArrayList<HSSFWorkbook>();
		// 1. Create new workbook
		HSSFWorkbook workbook = null;
		HSSFSheet worksheet = null;

		for (String client : clientsMap.keySet()) {

			HashMap<String, Integer> pageRowMap = new HashMap<String, Integer>();

			// 1. Create new workbook
			workbook = new HSSFWorkbook();

			// 2. Create new worksheet
			worksheet = workbook.createSheet(client);

			// 3. Define starting indices for rows and columns
			int startRowIndex = 0;
			int startColIndex = 0;

			HashMap<String, HashMap<String, ArrayList<Integer>>> logsMap = clientsMap
					.get(client);

			createTitle(worksheet, formData.getReport(), startRowIndex,
					startColIndex, logsMap.keySet().size());
			startRowIndex++;
			createPage(worksheet, "Pages", startRowIndex, startColIndex);

			for (String log : logsMap.keySet()) {
				startColIndex++;
				createHeader(worksheet, log, 1, startColIndex);

				HashMap<String, ArrayList<Integer>> pagesMap = logsMap.get(log);

				int row = 0;
				for (String page : pagesMap.keySet()) {

					ArrayList<Integer> timesList = pagesMap.get(page);

					if (!pageRowMap.containsKey(page)) {
						startRowIndex++;
						int specRow = startRowIndex;
						setDetail(worksheet, page, specRow, 0);
						pageRowMap.put(page, specRow);

					}

					row = pageRowMap.get(page);

					// 95%;
					int _95 = calcs.calculatePercentile(95, timesList);
					System.out.println("95% for client ["
							+ client
							+ "], log["
							+ log
							+ "], page["
							+ page
							+ "] using times["
							+ timesList.toArray(new Integer[timesList.size()])
									.toString() + "] is:[" + _95 + "]");

					// avg
					double _avg = calcs.calculateAverage(timesList);
					System.out.println("avg for client ["
							+ client
							+ "], log["
							+ log
							+ "], page["
							+ page
							+ "] using times["
							+ timesList.toArray(new Integer[timesList.size()])
									.toString() + "] is:[" + _avg + "]");

					// sdev
					double _stdev = calcs.calculateAverage(timesList);
					System.out.println("stdev for client ["
							+ client
							+ "], log["
							+ log
							+ "], page["
							+ page
							+ "] using times["
							+ timesList.toArray(new Integer[timesList.size()])
									.toString() + "] is:[" + _stdev + "]");

					if (formData.getReport().equals(
							ReportTypeEnum._95.getReportType())) {
						setDetail(worksheet, String.valueOf(_95), row,
								startColIndex);
					} else if (formData.getReport().equals(
							ReportTypeEnum._AVG.getReportType())) {
						setDetail(worksheet, String.valueOf(_avg), row,
								startColIndex);
					} else if (formData.getReport().equals(
							ReportTypeEnum._STDEV.getReportType())) {
						setDetail(worksheet, String.valueOf(_stdev), row,
								startColIndex);
					} else {
						// we have problems
					}
				}

			}
			// workbooks.add(workbook);

			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try {
				workbook.write(bos);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// byte[] oneFileContent = bos.toByteArray();
			String fileName = workbook.getSheetName(0) + ".xls";

			bosMap.put(fileName, bos);

		}
		// logger.debug("Downloading Excel report");

		// Map<String, ByteArrayOutputStream> bosMap =
		// convertToBosMap(workbooks);

		if (bosMap.size() == 1) {
			// this will loop once only
			for (String fileName : bosMap.keySet()) {
				writeService.write(response, bosMap.get(fileName), fileName);

			}
		} else {
			zipService.writeZip(response, bosMap);

		}

		/*
		 * // 7. Write to the output stream if (workbooks.size() == 1) { // if 1
		 * client, then 1 book, so write(response, workbooks.get(0)); } else {
		 * // if more than 1 client, more than 1 book, so compress all books //
		 * into zip file zipService.writeZip(response, bosMap); }
		 */

	}

	/*
	 * private Map<String, ByteArrayOutputStream> convertToBosMap(
	 * List<HSSFWorkbook> workbooks) { // covertWorkbooksToBos Map<String,
	 * ByteArrayOutputStream> bosMap = new HashMap<String,
	 * ByteArrayOutputStream>(); for (HSSFWorkbook wkbk : workbooks) {
	 * ByteArrayOutputStream bos = new ByteArrayOutputStream(); try {
	 * wkbk.write(bos); } catch (IOException e) { // TODO Auto-generated catch
	 * block e.printStackTrace(); }
	 * 
	 * //byte[] oneFileContent = bos.toByteArray(); String fileName =
	 * wkbk.getSheetName(0) + ".xls";
	 * 
	 * bosMap.put(fileName,bos); }
	 * 
	 * return bosMap;
	 * 
	 * }
	 */

	private void createPage(HSSFSheet worksheet, String page,
			int startRowIndex, int startColIndex) {

		worksheet.setColumnWidth(startColIndex, 15000);

		// Create the column headers
		HSSFRow rowHeader = worksheet.getRow(startRowIndex);
		if (rowHeader == null) {
			rowHeader = worksheet.createRow(startRowIndex);
			rowHeader.setHeight((short) 500);
		}

		HSSFCell cell1 = rowHeader.createCell(startColIndex);
		cell1.setCellValue(page);
		cell1.setCellStyle(createHeaderStyle(worksheet));

	}

	private void createTitle(HSSFSheet worksheet, String page,
			int startRowIndex, int startColIndex, int span) {

		worksheet.setColumnWidth(startColIndex, 15000);

		// Create the column headers
		HSSFRow rowHeader = worksheet.getRow(startRowIndex);
		if (rowHeader == null) {
			rowHeader = worksheet.createRow(startRowIndex);
			rowHeader.setHeight((short) 500);
		}

		HSSFCell cell1 = rowHeader.createCell(startColIndex);
		cell1.setCellValue(page);
		cell1.setCellStyle(createHeaderStyle(worksheet));
		worksheet.addMergedRegion(new CellRangeAddress(startRowIndex,
				startRowIndex, startColIndex, startColIndex + span));

	}

	private void createHeader(HSSFSheet worksheet, String header,
			int startRowIndex, int startColIndex) {
		// TODO Auto-generated method stub

		worksheet.setColumnWidth(startColIndex, 5000);

		// Create the column headers
		HSSFRow rowHeader = worksheet.getRow(startRowIndex);
		if (rowHeader == null) {
			rowHeader = worksheet.createRow(startRowIndex);
			rowHeader.setHeight((short) 500);
		}

		HSSFCell cell1 = rowHeader.createCell(startColIndex);
		cell1.setCellValue(header);
		cell1.setCellStyle(createHeaderStyle(worksheet));

	}

	public HSSFCellStyle createHeaderStyle(HSSFSheet worksheet) {
		// Create font style for the headers
		Font font = worksheet.getWorkbook().createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);

		// Create cell style for the headers
		HSSFCellStyle headerCellStyle = worksheet.getWorkbook()
				.createCellStyle();
		headerCellStyle.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
		headerCellStyle.setFillPattern(CellStyle.NO_FILL);
		headerCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		headerCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		headerCellStyle.setWrapText(true);
		headerCellStyle.setFont(font);
		headerCellStyle.setBorderBottom(CellStyle.BORDER_THIN);
		headerCellStyle.setBorderTop(CellStyle.BORDER_THIN);

		return headerCellStyle;

	}

	public HSSFCellStyle createDetailStyle(HSSFSheet worksheet) {
		// Create font style for the headers
		Font font = worksheet.getWorkbook().createFont();
		font.setBoldweight(Font.BOLDWEIGHT_NORMAL);

		// Create cell style for the headers
		HSSFCellStyle headerCellStyle = worksheet.getWorkbook()
				.createCellStyle();
		headerCellStyle.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
		headerCellStyle.setFillPattern(CellStyle.NO_FILL);
		headerCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		headerCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		headerCellStyle.setWrapText(true);
		headerCellStyle.setFont(font);
		// headerCellStyle.setBorderBottom(CellStyle.BORDER_THIN);

		return headerCellStyle;

	}

	public void setDetail(HSSFSheet worksheet, String value, int startRowIndex,
			int startColIndex) {

		// Create the column headers
		HSSFRow rowHeader = worksheet.getRow(startRowIndex);
		if (rowHeader == null) {
			rowHeader = worksheet.createRow(startRowIndex);
			// rowHeader.setHeight((short) 250);
		}

		HSSFCell cell1 = rowHeader.createCell(startColIndex);
		cell1.setCellValue(value);
		cell1.setCellStyle(createDetailStyle(worksheet));

	}

}
